package uuid

import (
	"encoding/binary"
	"math/rand"
	"time"

	"gitee.com/les49/esgo/encoding/base58"
)

const (
	DEVICE_ID_STRING_LEN          = 10
	PRODUCT_ID_STRING_LEN         = 6
	FILENAME_STRING_LEN           = 8
	UID_STRING_LEN                = 6
	MaxGenerateDeviceCount        = 100000
	MaxProductId           uint32 = 4026531839 // 0xEFFFFFFF
	MinProductId           uint32 = 656356768  // 58 * 58 * 58 * 58 * 58
)

var productIdSeed int64 = 0

func toLen(str string, length int) string {

	if len(str) == length {
		return str
	}

	for len(str) < length {
		str = "0" + str
	}

	for len(str) > length {
		str = str[1:]
	}

	return str
}

func GenerateDeviceId(count uint32) []string {
	devIds := make([]string, count)
	var i uint32
	var uuid uint64
	var err error

	if count == 0 || count > MaxGenerateDeviceCount {
		return nil
	}

	sf := &SnowFlake{productId: 0}

	for i = 0; i < count; i++ {
		uuid, err = sf.Generate()
		if nil != err {
			return nil
		}

		buf := make([]byte, binary.MaxVarintLen64)
		binary.BigEndian.PutUint64(buf, uuid)
		devIds[i] = base58.Encode(buf[2:])
		devIds[i] = toLen(devIds[i], DEVICE_ID_STRING_LEN)
		// fmt.Println("base58 devid, buf len:", len(buf), ", data:", devIds[i])
	}

	return devIds
}

func GenerateProductId() string {

	if productIdSeed < time.Now().Unix() {
		productIdSeed = time.Now().Unix()
	} else {
		productIdSeed = productIdSeed + 1
	}

	rand.New(rand.NewSource(productIdSeed))
	productId := MinProductId + (uint32)(rand.Uint32()%(MaxProductId-MinProductId))
	buf := make([]byte, binary.MaxVarintLen32)
	binary.BigEndian.PutUint32(buf, productId)

	strPid := base58.Encode(buf[:4])
	strPid = toLen(strPid, PRODUCT_ID_STRING_LEN)
	return strPid
}

func UidToString(uid uint32) string {
	var uidStr string
	buf := make([]byte, binary.MaxVarintLen32)
	binary.BigEndian.PutUint32(buf, uid)
	uidStr = base58.Encode(buf)
	return toLen(uidStr, UID_STRING_LEN)
}
